#pragma once
#include "rule.h"
#include "config.h"
#include <exception>

template <typename T>
class RuleSet
{
private:
	vector<Rule<T>> rules;
	bool hasRule(const Rule<T>& rule) const
	{
		for (vector<Rule<T>>::const_iterator i = rules.begin();
			 i != rules.end();
			 ++i)
			 if (rule == *i)
				 return true;
		return false;
	}

	bool hasConflictingRule(const Rule<T>& rule) const
	{
		for (vector<Rule<T>>::const_iterator i = rules.begin();
			i != rules.end();
			++i)
			if (i->conflicts(rule))
				return true;
		return false;
	}

	RuleSet& operator= (const RuleSet<T>& other) {};//NOTE: We might need the assignment operator later, but it is alright for now.
public:
	RuleSet() {};
	bool addRule(const Rule<T>& rule)
	{
#ifdef DUPLICATE_ALLOWED
#ifdef CONFLICT_ALLOWED
		//both duplicate and conflicts are allowed
		rules.push_back(rule);
#else
		//conflicts are not allowed, duplicates are
		if(!hasConflictingRule(rule))
			rules.push_back(rule);
#endif
#else
#ifdef CONFLICT_ALLOWED
		//duplicates not allowed, conflicts are
		if (!hasRule(rule))
			rules.push_back(rule);
#else
		//neither duplicate nor conflicts are allowed
		if(!hasRule(rule) && !hasConflictingRule(rule))
			rules.push_back(rule);
#endif
#endif
		return true;
	};


	T outCome (const vector<T> nbVals)
	{
		for (vector<Rule<T>>::const_iterator r = rules.begin(); r != rules.end(); ++r)
			if (r->applies(nbVals))
				return r->getLabel();
		//return RULEDOESNOTAPPLY;
		//exception& e("ruledoesnotapply");
		myException e = RULESETDOESNOTAPPLY;
		throw (e);
	}
	
};